import { HttpException, HttpStatus, Inject, Injectable } from '@nestjs/common';
import OpenAI from 'openai';
import { Toutiao } from './entities/toutiao.entity';
import { InjectEntityManager } from '@nestjs/typeorm';
import { EntityManager, LessThan, MoreThan } from 'typeorm';
import { History } from './entities/history.entity';
import { ConfigService } from '@nestjs/config';
import { render } from 'src/utils';

interface Results {
  e_id: number;
  title: string;
  content: string;
  picNo: number;
  picUrl: Urls[];
}
interface Urls {
  url: string;
}
interface HistoryDetail {
  reason: string;
  result: Results[];
}
@Injectable()
export class ApisService {
  @Inject(ConfigService)
  private configService: ConfigService;

  @InjectEntityManager()
  private manage: EntityManager;
  async createToutiao() {
    const key: string = this.configService.get('toutiao_key');
    try {
      const response = await fetch(
        `${this.configService.get('toutiao_list')}?key=${key}`,
      );
      const toutiaoList = await response.json();
      if (toutiaoList?.reason === 'success!') {
        const data = toutiaoList.result.data.filter(
          (i, index) => index > 1 && index < 11,
        );
        const toutiaoPromise = data.map((toutiao) => {
          return fetch(
            `${this.configService.get('toutiao_detail')}?key=${key}&uniquekey=${toutiao.uniquekey}`,
          );
        });
        // 返回fetch
        const responseList = await Promise.all(toutiaoPromise);
        console.log(1, responseList);
        // reponse.json()
        const responseJson = responseList.map((i) => {
          return new Promise((resolve, reject) => {
            i.json()
              .then((re) => resolve(re))
              .catch((err) => resolve(err));
          });
        });
        const resJson = await Promise.all(responseJson);
        console.log(2, resJson);
        const toutiaos = [];
        resJson.forEach((i: any, index) => {
          if (i?.reason === '查询成功') {
            const toutiao = new Toutiao();
            const detail = i.result.detail;
            toutiao.id = i.result.uniquekey;
            toutiao.title = detail.title;
            toutiao.date = detail.date;
            toutiao.category = detail.category;
            toutiao.author_name = detail.author_name;
            toutiao.url = detail.url;
            toutiao.content = i.result.content;
            const pics = [];
            for (let key in detail) {
              if (key.indexOf('thumbnail_pic') > -1 && detail[key]) {
                pics.push(detail[key]);
              }
            }
            if (pics.length) {
              toutiao.thumbnail_pic = pics.join(',');
            }
            toutiaos.push(toutiao);
          }
        });
        return await this.manage.save(Toutiao, toutiaos);
      } else {
        throw new HttpException('获取头条接口失败', HttpStatus.BAD_REQUEST);
      }
    } catch (error) {
      console.log(error);
    }
  }

  async createHistory() {
    try {
      const date = new Date();
      const day = date.getMonth() + 1 + '/' + date.getDate();
      const key = this.configService.get('history_key');
      const response = await fetch(
        `${this.configService.get('history_list_url')}?key=${key}&date=${day}`,
      );
      const historyList = await response?.json();
      // 查询详情
      if (historyList?.reason === 'success') {
        // api请求不能超50次每日
        const data =
          historyList?.result?.filter((i, index) => index < 50) ||
          [];

        const hisPromise = data.map((his) => {
          return fetch(
            `${this.configService.get('history_detail_url')}?key=${key}&e_id=${his.e_id}`,
          );
        });
        // 返回fetch

        const responseList = await Promise.all(hisPromise);
        // reponse.json()
        const responseJson = responseList.map((i) => {
          return new Promise((resolve, reject) => {
            i
              ?.json()
              .then((re) => resolve(re))
              .catch((err) => resolve(err)); // reject，promiseAll会报错
          });
        });
        const resJson = await Promise.all(responseJson);
        console.log(resJson, 'resJsonXXXX');
        const historys = [];
        resJson.forEach((i: HistoryDetail, index) => {
          if (
            i?.reason === 'success' &&
            i?.result?.[0] &&
            historyList?.result?.[index] &&
            i?.result?.[0]?.content?.length < 10000
          ) {
            const history = new History();
            const detail = i.result[0];
            const baseInfo = historyList.result[index];
            history.content = detail.content || '';
            // 9张图最多
            history.picUrl =
              detail?.picUrl
                .filter((picss, idx) => idx < 10)
                .map((pic) => pic.url)
                .join(',') || '';
            history.id = detail.e_id;
            history.title = detail.title;
            history.day = baseInfo.day;
            history.date = baseInfo.date;
            historys.push(history);
          }
        });
        return await this.manage.save(History, historys);
      } else {
        throw new HttpException(
          '获取当年今日文章接口失败',
          HttpStatus.BAD_REQUEST,
        );
      }
    } catch (error) {
      console.log(error);
    }
  }

  async findAllToutiao() {
    return await this.manage.find(Toutiao, {
      where: {},
      select: [
        'id',
        'title',
        'thumbnail_pic',
        'category',
        'url',
        'author_name',
      ],
    });
  }

  async getToutiaoDetail(id: string) {
    return await this.manage.findOneBy(Toutiao, { id: id });
  }

  async findAllHistory() {
    const date = new Date();
    const day: string = date.getMonth() + 1 + '/' + date.getDate();
    return await this.manage.find(History, {
      where: { day: day },
      select: ['id', 'title', 'picUrl', 'day', 'date'],
    });
  }

  async getHistoryDetail(id: number) {
    const res: History = await this.manage.findOneBy(History, { id: id });
    // front article
    const front: History[] = await this.manage.find(History, {
      where: { id: LessThan(id) },
      order: { id: 'DESC' },
      take: 1,
    });
    // next article
    const next: History[] = await this.manage.find(History, {
      where: { id: MoreThan(id) },
      order: { id: 'ASC' },
      take: 1,
    });
    const nextId: number | null = next?.[0]?.id || null;
    const frontId: number | null = front?.[0]?.id || null;
    const nextTitle: string = next?.[0]?.title || '';
    const frontTitle: string = front?.[0]?.title || '';
    // load pictures
    const pic: string[] = res?.picUrl?.split(',') || [];
    let picHtml: string = '';
    for (let i = 0; i < pic.length; i++) {
      pic[i]
        ? (picHtml += `<img src="${pic[i]}">`)
        : '';
    }
    const host: string =
      this.configService.get('environment') === 'development'
        ? 'http://localhost:3000'
        : 'http://www.huangqingjian.top/api';
    const frontLink: string = frontId
      ? `<a href="${host}/apis/getHistoryDetail/${frontId}">上一篇: ${frontTitle}</a>`
      : `<span></span>`;
    const nextLink: string = nextId
      ? `<a href="${host}/apis/getHistoryDetail/${nextId}">下一篇: ${nextTitle}</a>`
      : `<span></span>`;
    const url: string =
      this.configService.get('environment') === 'development'
        ? 'http://localhost:9567/#/'
        : 'http://www.huangqingjian.top/#/';
    return render(res, picHtml, frontLink, nextLink, url);
  }

  /**
   * 异步函数，用于调用阿里云通义千问模型进行聊天问答
   * @param question - 用户提出的问题
   * @returns 模型返回的答案
   */
  async getOpenAi(question: string) {
    try {
      const openai = new OpenAI({
        // 若没有配置环境变量，请用百炼API Key将下行替换为：apiKey: "sk-xxx",
        apiKey: this.configService.get('tong_tong_key'),
        baseURL: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
      });
      const completion = await openai.chat.completions.create({
        model: 'qwen-plus', //模型列表：https://help.aliyun.com/zh/model-studio/getting-started/models
        stream: true,
        messages: [
          { role: 'system', content: 'You are a helpful assistant.' },
          { role: 'user', content: question },
        ],
      });
      const chunks: string[] = [];
      for await (const chunk of completion) {
        // console.log(chunk?.choices?.[0]?.delta?.content||'sb', 'get')
        chunks.push(chunk?.choices?.[0]?.delta?.content || '');
      }
      return chunks;
      // return await completion.choices?.[0]?.message?.content;
    } catch (error) {
      console.log(`错误信息：${error}`);
      console.log(
        '请参考文档：https://help.aliyun.com/zh/model-studio/developer-reference/error-code',
      );
      throw new HttpException(error, HttpStatus.BAD_REQUEST);
    }
  }
}
